﻿SmitearWebGL.Scene.QuadTreeNode = Class.extend(
{
	/* * * * * * * * constructor * * * * * * * */

	init : function()
	{
		this._super();
		this._registClass( "SmitearWebGL.Scene.QuadTreeNode" );

		/* * * * * * * * public property * * * * * * * */
		
		this.levelFlag = {};

		/* * * * * * * * private property * * * * * * * */

		this._childNode = new Array( 4 );
		this._members = new Array( 1024 );
		this._parentNode = null;
		this._numMember = 0;

		this._yLocalMask = new SmitearWebGL.Core.Math.BitFlags();
		this._yMask = new SmitearWebGL.Core.Math.BitFlags();
		this._status = new SmitearWebGL.Core.Math.BitFlags();
	}
	,
	isEmpty : function()
	{
		return this._yMask.isEmpty();
	}
	,
	getYMask : function()
	{
		return this._yMask;
	}
	,
	getLocalYMask : function()
	{
		return this._yLocalMask;
	}
	,
	setStatus : function( flagBit, value )
	{
		this._status.setBit( flagBit, value );
	}
	,
	getStatus : function( status )
	{
		return this._status.testBit( status );
	}
	,
	rebuildLocalYMask : function()
	{
		this._yLocalMask.clear();

		for( var i = 0; i < this._numMember; ++ i )
		{
			this._yLocalMask.setFlagsByFlags( this._members[i].extra.yMask );
		}

		this.rebuildYMask();
	}
	,
	rebuildYMask : function()
	{
		this._yMask = this._yLocalMask;

		for ( var i = 0; i < this._childNode.length; ++ i )
		{
			if ( this._childNode[i] )
			{
				this._yMask.setFlagsByFlags( this._childNode[i].getYMask() );
			}
		}
	}
	,
	descendantMemberAdded : function( yMask )
	{
		this._yMask.setFlags( yMask );

		if ( this._parentNode )
		{
			this._parentNode.descendantMemberAdded( yMask );
		}
	}
	,
	descendantMemberRemoved : function()
	{
		this.rebuildYMask();

		if ( this._parentNode )
		{
			this._parentNode.descendantMemberRemoved();
		}
	}
	,
	setup : function( parent, child0, child1, child2, child3 )
	{
		$THROW( this._parentNode == null, "已存在父节点" );
		this._parentNode = parent;

		this._childNode[0] = child0;
		this._childNode[1] = child1;
		this._childNode[2] = child2;
		this._childNode[3] = child3;
	}
	,
	addMember : function( member, rect )
	{
		this.updateMember( member, rect );
	}
	,
	updateMember : function( member, rect )
	{
		var yMask = SmitearWebGL.Scene.QuadTreeNode.yMask( rect.y0, rect.y1 );

		if ( member.getQuadTreeNode() != this )
		{
			if ( member.getQuadTreeNode() )
			member.getQuadTreeNode().removeMember( member );

			this._yLocalMask.setFlags( yMask );
			this.descendantMemberAdded( yMask );
			this._members[this._numMember] = member;

			member.setQuadTreeNode( this );
			member.extra.nodeIdx = this._numMember;
			if ( ! member.extra.yMask ) member.extra.yMask = new SmitearWebGL.Core.Math.BitFlags();
			member.extra.yMask.set( yMask );

			++ this._numMember;
		}

		this.setStatus( SmitearWebGL.Scene.QuadTreeNode.eStates.k_yMaskDirty, true );
	}
	,
	removeMember : function( member )
	{
		$THROW( member.getQuadTreeNode() == this, "此成员不属于该节点" );

		var idx = member.extra.nodeIdx;

		if ( idx != this._numMember - 1 )
		{
			var lastMember = this._members[this._numMember - 1];
			this._members[idx] = lastMember;
			lastMember.extra.nodeIdx = idx;
		}

		this._members[this._numMember - 1] = null;
		-- this._numMember;

		this.rebuildLocalYMask();

		if ( this._parentNode )
		{
			this._parentNode.descendantMemberRemoved();
		}
	}
	,
	testLocalMembersForSearchResults : function( searchResults, numResults, yMask, nearClip, farClip )
	{
		if ( this._yLocalMask.testAny( yMask ) )
		{
			for( var i = 0; i < this._numMember; ++ i )
			{
				var object = this._members[i];

				if ( object && object.extra.yMask.testAny( yMask ) )
				{
					if ( object.getBoundingBox().testRect( nearClip, farClip ) )
					{
						searchResults[numResults ++ ] = object;
					}
				}
			}
		}

		return numResults;
	}
	,
	testLocalMembersForSearchResultsByRect : function( searchResults, numResults, yMask, trueRect, nearClip, farClip )
	{
		if ( this._yLocalMask.testAny( yMask ) )
		{
			for( var i = 0; i < this._numMember; ++ i )
			{
				var object = this._members[i];

				if ( object && object.extra.yMask.testAny( yMask ) )
				{
					var aabb = object.getBoundingBox();

					if ( SmitearWebGL.Core.Geometry.Rect.intersectRect( trueRect, aabb.getWorldAABB(), null ) )
					{
						if ( aabb.testRect( nearClip, farClip ) )
						{
							searchResults[numResults ++ ] = object;
						}
					}
				}
			}
		}

		return numResults;
	}
	,
	updateBeforeRender : function()
	{
	}
	,
	updateAfterRender : function()
	{
		this.setStatus( SmitearWebGL.Scene.QuadTreeNode.eStates.k_yMaskDirty, true );
	}
	,
	release : function()
	{
		$THROW( this._yMask.value == 0, "四叉树还存在成员没有被释放" );
			
		this._childNode = null;
		this._members = null;
		this._parentNode = null;
		this._numMember = 0;
		
		this._yLocalMask = null;
		this._yMask = null;
		this._status = null;
		
		this.levelFlag = null;
	}
}
);

SmitearWebGL.Scene.QuadTreeNode.yMask = function( ymin, ymax )
{
	var high = ( 1 << ymax );
	var low = ( 1 << ymin );
	var setMask = high - 1;
	var clearMask = low - 1;

	var result = setMask;
	if ( ymin )
	{
		result &= ~ clearMask;
	}
	result |= high;
	result |= low;

	return result >>> 0;
}

SmitearWebGL.Scene.QuadTreeNode.eStates =
{
	k_yMaskDirty : 0,
	totalState : 1
}